package com.probox.common.entity.utils;

import cn.hutool.core.io.resource.ClassPathResource;
import okhttp3.HttpUrl;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.io.FileNotFoundException;
import java.security.*;
import java.security.cert.X509Certificate;
import java.util.Base64;
import java.util.UUID;

/**
 * 封装请求头
 * @author Kite
 * @date 2021/7/8
 */
public class WeChatRequest {
    //商户列号
    private static String serize_no = "";

    private static String url = "apiclient_cert.p12";

    //服务商商户ID
    private final static String mercId = "1609865431";

    //编码
    private static final String charset = "UTF-8";


    private static KeyPair keyPair;
    private final Object lock = new Object();
    private KeyStore store;

    /**
     * Get请求
     * @param requestUrl 请求地址
     * @return
     */
    public String weChatGet(String requestUrl){
        String body = "";
        HttpGet httpGet = new HttpGet(requestUrl);
        String post = null;
        try {
            post = getToken("GET", HttpUrl.parse(requestUrl), url,body);
            post = "WECHATPAY2-SHA256-RSA2048 " + post;
            httpGet.addHeader("Accept", "application/json");
            httpGet.setHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
            httpGet.setHeader("Authorization", post);
            CloseableHttpClient httpClient = HttpClients.createDefault();
            CloseableHttpResponse response = httpClient.execute(httpGet);
            HttpEntity entity = response.getEntity();
            body = EntityUtils.toString(entity, charset);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return body;
    }

    //封装Authorization

    public static String getAuthorization(String crequestUrl,String body) throws Exception {
        String post = getToken("POST", HttpUrl.parse(crequestUrl),url, body);
        return "WECHATPAY2-SHA256-RSA2048 " + post;
    }
    /**
     * 生成组装请求头
     *
     * @param method             请求方式
     * @param url                请求地址
     * @param privateKeyFilePath 私钥路径
     * @param body               请求体
     * @return 组装请求的数据
     * @throws Exception
     */
    static String getToken(String method, HttpUrl url, String privateKeyFilePath, String body) throws Exception {
        String nonceStr = UUID.randomUUID().toString().replace("-", "");
        long timestamp = System.currentTimeMillis() / 1000;
        String message = buildMessage(method, url, timestamp, nonceStr, body);
        String signature = sign(message.getBytes("UTF-8"), privateKeyFilePath, mercId);
        return "mchid=\"" + mercId + "\","
                + "nonce_str=\"" + nonceStr + "\","
                + "timestamp=\"" + timestamp + "\","
                + "serial_no=\"" + serize_no + "\","
                + "signature=\"" + signature + "\"";
    }


    /**
     * 组装签名加载
     *
     * @param method    请求方式
     * @param url       请求地址
     * @param timestamp 请求时间
     * @param nonceStr  请求随机字符串
     * @param body      请求体
     * @return 组装的字符串
     */
    static String buildMessage(String method, HttpUrl url, long timestamp, String nonceStr, String body) {
        String canonicalUrl = url.encodedPath();
        if (url.encodedQuery() != null) {
            canonicalUrl += "?" + url.encodedQuery();
        }
        return method + "\n"
                + canonicalUrl + "\n"
                + timestamp + "\n"
                + nonceStr + "\n"
                + body + "\n";
    }

    /**
     * 生成签名
     *
     * @param message            请求体
     * @param privateKeyFilePath 私钥的路径
     * @return 生成base64位签名信息
     * @throws Exception
     */
    static String sign(byte[] message, String privateKeyFilePath, String mercId) throws Exception {
        Signature sign = Signature.getInstance("SHA256withRSA");
        WeChatRequest weChatRequest = new WeChatRequest();
        PrivateKey privateKey = weChatRequest.createPKCS12(privateKeyFilePath, "Tenpay Certificate", mercId).getPrivate();
        sign.initSign(privateKey);
        sign.update(message);
        return Base64.getEncoder().encodeToString(sign.sign());
    }

    /**
     * 获取公私钥.
     *
     * @param keyPath  the key path
     * @param keyAlias the key alias
     * @param keyPass  password
     * @return the key pair
     */
    public KeyPair createPKCS12(String keyPath, String keyAlias, String keyPass) throws FileNotFoundException {
        if (keyPair != null) {
            return keyPair;
        }
          ClassPathResource resource = new ClassPathResource(url);
        char[] pem = keyPass.toCharArray();
        try {
            synchronized (lock) {
                if (store == null) {
                    synchronized (lock) {
                        store = KeyStore.getInstance("PKCS12");
                        store.load(resource.getStream(), pem);
                    }
                }
            }
            X509Certificate certificate = (X509Certificate) store.getCertificate(keyAlias);
            certificate.checkValidity();

            // 证书的序列号 也有用
            String serialNumber = certificate.getSerialNumber().toString(16).toUpperCase();
            serize_no = serialNumber;
            // 证书的 公钥
            PublicKey publicKey = certificate.getPublicKey();
            // 证书的私钥
            PrivateKey storeKey = (PrivateKey) store.getKey(keyAlias, pem);

            keyPair = new KeyPair(publicKey, storeKey);
            return keyPair;

        } catch (Exception e) {
            throw new IllegalStateException("Cannot load keys from store: " , e);
        }
    }
}
